home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / a / a_funk / hammap1.tos / LINKINFO / LINKINFO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-06  |  51.1 KB  |  2,080 lines

  1. /* Versionsangaben */
  2. #define ID "$Header: LINKINFO DL6SDC/DG2SBV 1.04 930802$"
  3. #define VERSION "LINKINFO Version 1.04 (930802) by DL6SDC, DG2SBV"
  4. #define FILEVERS 0x100
  5. /*static char *rcsid=ID;*/
  6.  
  7. /* Konfiguration */
  8. /* Defines:
  9.    a) Maschinentyp
  10.       Entweder UNIX, MSDOS oder ATARI
  11.    b) SEG: Schaltet auf Segmentierung. Muss auch auf Dose explizit gesetzt
  12.       werden!
  13.    c) NDEBUG/DEBUG: Debugging aus/an. Default ist Debug an.
  14.       im Debug-Modus sind unter UNIX Optionen fuer die Dateinamen gestattet.
  15.       Der Debug-Modus ist unter UNIX eine Sicherheitsluecke, so dass man
  16.       einem Debug-Linkinfo keinesfalls set user id geben sollte!
  17.    d) COLUMNS: Anzahl Spalten bei der Ausgabe. Default: 79
  18.  */
  19.  
  20. #ifndef COLUMNS
  21. #define COLUMNS 79
  22. #endif
  23.  
  24. #ifdef NDEBUG
  25. #ifdef DEBUG
  26. ErRoR /* Debug und Nodebug geht nicht gleichzeitig */
  27. #endif
  28. #undef DEBUG
  29. #else
  30. #undef DEBUG /* Falls mit -DDEBUG compiliert wird */
  31. #define DEBUG
  32. #endif
  33.  
  34. #ifdef SEG
  35. #define SEGMENT64K 1
  36. #else
  37. #define SEGMENT64K 0 /* max. 64 KB am Stueck */
  38. #endif
  39.  
  40. #ifdef UNIX
  41. #ifdef SEG
  42. ErRoR /* Was ist denn ein UNIX mit 64KB-Segmenten?! */
  43. #endif
  44. #define MEMLIMIT   0 /* eng begrenzter Speicher -> Verwende coreleft() */
  45. #if defined (MSDOS) || defined (ATARI)
  46. ErRoR
  47. #endif
  48. #else
  49. #define MEMLIMIT   1 /* eng begrenzter Speicher -> Verwende coreleft() */
  50. #endif
  51.  
  52. #ifdef MSDOS
  53. #if defined (ATARI)
  54. ErRoR
  55. #endif
  56. #endif
  57.  
  58. #if !defined (UNIX) && !defined (MSDOS) && !defined (ATARI)
  59. ErRoR
  60. #endif
  61.  
  62. #if SEGMENT64K
  63. #define INDIRECT 1
  64. #else
  65. #define INDIRECT 0
  66. #endif
  67. #ifndef NDEBUG
  68. #define OPTIONS 1   /* Optionen fuer Filenamen erlaubt? In fernbedienbarer
  69.              * Version besser ausschalten!!!!!
  70.              */
  71. #else
  72. #define OPTIONS 0
  73. #endif
  74.  
  75. #if MEMLIMIT || SEGMENT64K
  76. #define MEMRESV 16384
  77. #endif
  78.  
  79. /* Includes */
  80.  
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <assert.h>
  84. #include <ctype.h>
  85. #include <string.h>
  86.  
  87. #ifdef UNIX
  88. #include <sys/types.h>
  89. #include <sys/stat.h>
  90. #else
  91. #include <time.h>
  92. #ifdef ATARI
  93. #include <ext.h>
  94. #else
  95. #include <sys/stat.h>
  96. #endif
  97. /* E.g. TURBO-C */
  98. #endif
  99.  
  100. /* Defines */
  101.  
  102. #define NOT_IMPLEMENTED assert(0)
  103.  
  104. #ifdef UNIX
  105. #define ASCII_FILENAME "/usr/local/lib/digimap.dat"
  106. #define BIN_FILENAME "/usr/local/lib/digimap.bin"
  107. #define INFO_TMP "/tmp/digiinfo.%d"
  108. #else
  109. #define ASCII_FILENAME "digimap.dat"
  110. #define BIN_FILENAME "digimap.bin"
  111. #define INFO_TMP "digiinfo.tmp"
  112. #endif
  113.  
  114. #if defined(__TURBOC__) || defined(__STDC__) || defined(LATTICE)
  115. #define _ARGS(a) a
  116. #else
  117. #define _ARGS(a) ()
  118. #define const
  119. #endif
  120.  
  121. #if INDIRECT
  122. #define digi(a) (digitab[(a)])
  123. #define link(a) (linktab[(a)])
  124. #else
  125. #define digi(a) (digitab+(a))
  126. #define link(a) (linktab+(a))
  127. #endif
  128.  
  129. #define infty     32767  /* Passt noch in jedes int... */
  130.  
  131. #define LINK_WIRE 9950
  132. #define LINK_38K4 9900
  133. #define LINK_19K2 9800
  134. #define LINK_9K6  9700
  135. #define LINK_4K8  9600
  136. #define LINK_2K4  9400
  137. #define LINK_1K2  9000
  138. #define LINK_300  8000
  139. #define LINK_NONE 0000
  140.  
  141. #define P_WIRE    3
  142. #define P_38K4    6
  143. #define P_19K2    12
  144. #define P_9K6     18
  145. #define P_4K8     24
  146. #define P_2K4     37
  147. #define P_1K2     63
  148. #define P_300     133
  149. #define P_NONE    infty
  150.  
  151. #define SYM_WIRE  '%'
  152. #define SYM_38K4  '|'
  153. #define SYM_19K2  '!'
  154. #define SYM_9K6   '#'
  155. #define SYM_4K8   '@'
  156. #define SYM_2K4   '$'
  157. #define SYM_1K2   ' '
  158. #define SYM_300   '"'
  159. #define SYM_NONE  '&'
  160.  
  161. #define STR_WIRE  "<Draht>"
  162. #define STR_38K4  "<38K4>"
  163. #define STR_19K2  "<19K2>"
  164. #define STR_9K6   "<9K6>"
  165. #define STR_4K8   "<4K8>"
  166. #define STR_2K4   "<2K4>"
  167. #define STR_1K2   "<1K2>"
  168. #define STR_300   "<300>"
  169. #define STR_NONE  "<>-X-<>"
  170.  
  171. #define NAME_WIRE "Draht"
  172. #define NAME_38K4 "38400 Baud"
  173. #define NAME_19K2 "19200 Baud"
  174. #define NAME_9K6  "9600 Baud"
  175. #define NAME_4K8  "4800 Baud"
  176. #define NAME_2K4  "2400 Baud"
  177. #define NAME_1K2  "1200 Baud"
  178. #define NAME_300  "300 Baud"
  179. #define NAME_NONE "Nicht in Betrieb/im Bau/geplant"
  180.  
  181. #define TYPE_USER 0 /* User, der inoffizielle Links betreibt */
  182. #define TYPE_SATG 1 /* Sat-Gate */
  183. #define TYPE_BBS  2 /* Mailbox */
  184. #define TYPE_DIGI 3 /* Digipeater */
  185. #define TYPE_CLU  4 /* DX-Cluster */
  186. #define TYPE_WX   5 /* Wetterstation */
  187. #define TYPE_TCP  6 /* TCP/IP-Knoten */
  188. #define TYPE_TNC  7 /* Link-TNC */
  189.  
  190. #define MAXINFO 64
  191.  
  192. /* typedefs */
  193.  
  194. typedef struct{
  195.   char call[7];
  196.   short laenge;  /* 5' - Einheiten ab 180 Grad westl. nach Osten */
  197.   short breite;  /* 2.5' - Einheiten ab 90 Grad suedl. nach Norden */
  198.   short type;    /* Werte s.o. */
  199.   long qrg;      /* In kHz, Bereich also 0-~2000000 MHz... */
  200.   unsigned char num_links;
  201.   unsigned short links;
  202.   /*char info[MAXINFO];    /* Infofeld */
  203. }DIGI_T;
  204. #define FILE_DIGI_T_LENGTH 20
  205.  
  206. typedef struct{
  207.   unsigned short neighbour;
  208.   unsigned short pquality;
  209. }LINK_T;
  210. #define FILE_LINK_T_LENGTH 4
  211.  
  212. typedef struct {
  213.   unsigned short neighbour;
  214.   unsigned short pquality;
  215.   short digi;
  216. } SEARCH_T;
  217. /* Variablen */
  218.  
  219. #if INDIRECT
  220. DIGI_T **digitab;
  221. LINK_T **linktab;
  222. #else
  223. DIGI_T *digitab;
  224. LINK_T *linktab;
  225. #endif
  226. int digis,links;
  227.  
  228. char *ascii_filename;
  229. char *bin_filename;
  230.  
  231. FILE *ascfile;
  232. FILE *tmp_file;
  233. char tmpname [80];
  234. int tmp_exists = 0;
  235.  
  236. FILE *binfile;
  237. long info_offset;
  238. int sorted;
  239.  
  240. /* Prototypes */
  241.  
  242. char * parse_call _ARGS((char *, char [7]));
  243. int search_digi _ARGS((char [7]));
  244. void dump _ARGS((void));
  245. void alloc _ARGS((int, int));
  246. void free_data _ARGS((void));
  247. void load_digis _ARGS((void));
  248. void load_links _ARGS((void));
  249. void check_links _ARGS((void));
  250. void countasc _ARGS((int *, int *));
  251. int callcmp _ARGS((char *, char *));
  252. void printcoord _ARGS((int, int));
  253. void read_info _ARGS((char *, int));
  254. char *asctype _ARGS((int));
  255. char *vasctype _ARGS((int));
  256. char *asccall _ARGS((char [7]));
  257. char *stripstr _ARGS((char *));
  258. char *stripcall _ARGS((char [7]));
  259. void printloc _ARGS((short,short));
  260. void vausgabe _ARGS((int));
  261. void ausgabe _ARGS((int));
  262. void compile_data _ARGS((void));
  263. void data_info _ARGS((void));
  264. void load_data _ARGS((void));
  265. void find_qrg _ARGS((char *));
  266. int info_call _ARGS((char *));
  267. void info_prefix _ARGS((char *));
  268. void exclude_call _ARGS((char [7], char [7], char [7]));
  269. void exclude_link _ARGS((char [7], char [7]));
  270. void do_exclusions _ARGS((int,char **, char *, char *));
  271. void print_quality _ARGS((int));
  272. void print_path _ARGS((int, SEARCH_T *));
  273. void print_distances _ARGS((int, SEARCH_T *));
  274. void found_route _ARGS((int, SEARCH_T *));
  275. void find_route _ARGS((char *,char *));
  276. void stop _ARGS((char *));
  277. void internal _ARGS((int,char *));
  278. void pstop _ARGS((char *));
  279. void parse_options _ARGS((int,char **));
  280. int asciinewer _ARGS((void));
  281. int put_num _ARGS((FILE*,long,int));
  282. int get_numl _ARGS((FILE*,long*,int));
  283. int iswhitespace _ARGS((char));
  284. void strtoupper _ARGS((char*));
  285. int qthvalid _ARGS((char*));
  286. int qrgvalid _ARGS((char*));
  287. void copyright _ARGS((void));
  288. void usage _ARGS((void));
  289. int main _ARGS((int,char**));
  290. int checksp _ARGS((int, char **));
  291.  
  292. char *parse_call (text, call)
  293. char *text;
  294. char call [7];
  295. {
  296.   int i;
  297.   char *str = text;
  298.   while (*str && iswhitespace (*str)) str ++;
  299.   for (i = 0; i < 6 && isalnum (*str); i ++) {
  300.     call [i] = toupper (*str);
  301.     str ++;
  302.   }
  303.   if (i == 0) return text;
  304.   while (i < 6) call [i ++] = ' ';
  305.   if (*str == '-') {
  306.     str ++;
  307.     switch (toupper (*str)) {
  308.     case '0':
  309.     case '2':
  310.     case '3':
  311.     case '4':
  312.     case '5':
  313.     case '6':
  314.     case '7':
  315.     case '8':
  316.     case '9':
  317.       call [6] = *str - '0';
  318.       break;
  319.     case 'A':
  320.     case 'B':
  321.     case 'C':
  322.     case 'D':
  323.     case 'E':
  324.     case 'F':
  325.       call [6] = toupper (*str) - 'A' + 10;
  326.       break;
  327.     case '1':
  328.       str ++;
  329.       if (*str < '0' || *str > '5') {
  330.     call [6] = 1;
  331.     return str;
  332.       }
  333.       call [6] = *str - '0' + 10;
  334.       break;
  335.     default:
  336.       return text;
  337.     }
  338.     str ++;
  339.   } else {
  340.     call [6] = 0;
  341.   }
  342.   return str;
  343. }
  344. int search_digi (call)
  345. char call [7];
  346. {
  347.   if (sorted) {
  348.     int min, max, half, cmp;
  349.     min = 0; max = digis; /* max ausschliesslich */
  350.     while (min < max) {
  351.       half = (min + max) / 2;
  352.       cmp = callcmp (digi (half) -> call, call);
  353.       if (cmp == 0) return half;
  354.       if (cmp < 0) {
  355.     min = half + 1;
  356.       } else {
  357.     max = half;
  358.       }
  359.     }
  360.   } else {
  361.     int i;
  362.     for (i = 0; i < digis; i ++) {
  363.       if (!callcmp (digi (i) -> call, call)) return i;
  364.     }
  365.   }
  366.   return -1;
  367. }
  368. void dump ()
  369. {
  370.   int i;
  371.   DIGI_T *dt;
  372.   LINK_T *lt;
  373.   char it [MAXINFO];
  374.   if (put_num (binfile, FILEVERS | (sorted ? 0x8000 : 0), 2) != 2)
  375.     pstop (bin_filename);
  376.   if (put_num (binfile, digis, 2) != 2) pstop (bin_filename);
  377.   if (put_num (binfile, links, 2) != 2) pstop (bin_filename);
  378.   for (i = 0; i < digis; i ++) {
  379.     dt = digi (i);
  380.     if (fwrite (dt -> call, sizeof (char), 7, binfile) != 7)
  381.       pstop (bin_filename);
  382.     if (put_num (binfile, dt -> laenge, 2) != 2) pstop (bin_filename);
  383.     if (put_num (binfile, dt -> breite, 2) != 2) pstop (bin_filename);
  384.     if (put_num (binfile, dt -> type, 2) != 2) pstop (bin_filename);
  385.     if (put_num (binfile, dt -> qrg, 4) != 4) pstop (bin_filename);
  386.     if (put_num (binfile, dt -> num_links, 1) != 1) pstop (bin_filename);
  387.     if (put_num (binfile, dt -> links, 2) != 2) pstop (bin_filename);
  388.   }
  389.   for (i = 0; i < links; i ++) {
  390.     lt = link (i);
  391.     if (put_num (binfile, lt -> neighbour, 2) != 2) pstop (bin_filename);
  392.     if (put_num (binfile, lt -> pquality, 2) != 2) pstop (bin_filename);
  393.   }
  394.   for (i = 0; i < digis; i ++) {
  395.     if (fread (it, sizeof (char), MAXINFO, tmp_file) != MAXINFO)
  396.       pstop (tmpname);
  397.     if (fwrite (it, sizeof (char), MAXINFO, binfile) != MAXINFO)
  398.       pstop (bin_filename);
  399.   }
  400. }
  401. void alloc (digis, links)
  402. int digis, links;
  403. {
  404. #if MEMLIMIT
  405. #if INDIRECT
  406.   /* if( digis*sizeof(DIGI_T) + links*sizeof(LINK_T) +
  407.      (digis+links) * sizeof(DIGI_T*) + MEMRESV > coreleft() )
  408.     stop("Nicht genug Speicher"); */
  409.   /* coreleft() gibt nur die Groesse von einem Segment zurueck, also
  410.      ist diese Bedingung zu streng. */
  411. #else
  412.   if( digis*sizeof(DIGI_T) + links*sizeof(LINK_T) +
  413.      MEMRESV > coreleft() )
  414.     stop("Nicht genug Speicher");
  415. #endif
  416. #endif
  417. #if INDIRECT
  418.   if( !(digitab = (DIGI_T **) calloc(digis, sizeof(DIGI_T *))))
  419.     pstop(bin_filename);
  420.   if( !(linktab = (LINK_T **) calloc(links, sizeof(LINK_T *))))
  421.     pstop(bin_filename);
  422.   {
  423.     DIGI_T *hd; LINK_T *hl;
  424.     int d, di, l, li, i;
  425.     DIGI_T **ld; LINK_T **ll;
  426. #if SEGMENT64K
  427.     d=(int)((65536l - MEMRESV) / sizeof(DIGI_T));
  428.     l=(int)((65536l - MEMRESV) / sizeof(LINK_T));
  429. #else
  430.     d=digis;l=links;
  431. #endif
  432.     for(ld = digitab, di=digis; di; di-=d){
  433.       if(d > di) d = di;
  434.       hd = (DIGI_T*) calloc(d, sizeof(DIGI_T));
  435.       if(!hd) pstop(bin_filename);
  436.       for(i=0; i<d; i++){
  437.     *ld++=hd;
  438.     hd++;
  439.       }
  440.     }
  441.     for(ll = linktab, li=links; li; li-=l){
  442.       if(l > li) l = li;
  443.       hl = (LINK_T*) calloc(l, sizeof(LINK_T));
  444.       if(!hl) pstop(bin_filename);
  445.       for(i=0; i<l; i++){
  446.     *ll++=hl;
  447.     hl++;
  448.       }
  449.     }
  450.   }
  451. #else
  452.   digitab = (DIGI_T*) calloc(digis, sizeof(DIGI_T));
  453.   if(!digitab) pstop(bin_filename);
  454.   linktab = (LINK_T*) calloc(links, sizeof(LINK_T));
  455.   if(!linktab) pstop(bin_filename);
  456. #endif
  457. }
  458. void free_data ()
  459. {
  460. #if INDIRECT
  461. #if SEGMENT64K
  462.   int d, l;
  463.   int i;
  464.   d=(int)((65536l - MEMRESV) / sizeof(DIGI_T));
  465.   l=(int)((65536l - MEMRESV) / sizeof(LINK_T));
  466.   for (i = 0; i < digis; i += d) {
  467.     free (digitab [i]);
  468.   }
  469.   for (i = 0; i < links; i += l) {
  470.     free (linktab [i]);
  471.   }
  472. #else
  473.   free (digitab [0]);
  474.   free (linktab [0]);
  475. #endif
  476.   free (digitab);
  477.   free (linktab);
  478. #else
  479.   free (digitab);
  480.   free (linktab);
  481. #endif
  482.   if (fclose (binfile) == EOF) pstop (bin_filename);
  483. }
  484. void load_digis ()
  485. {
  486.   int d, l;
  487.   long line_nr;
  488.   char prevcall [7];
  489.   char currcall [7];
  490.   char buf [2048];
  491.   char *bp, *bp2;
  492.   DIGI_T *dt;
  493.   int i;
  494.   sorted = 1;
  495.   line_nr = d = l = 0;
  496.   for (i = 0; i < 7; i ++)
  497.     prevcall [i] = 0;
  498.   while (fgets (buf, 2048, ascfile)) {
  499.     line_nr ++;
  500.     for (bp = buf; *bp && iswhitespace (*bp); bp ++)
  501.       ;
  502.     if (!*bp || *bp == '#') continue;
  503.     dt = digi (d);
  504.     d ++;
  505.     /* Call */
  506.     bp2 = parse_call (bp, currcall);
  507.     if (bp2 == bp) {
  508.       printf ("%s: Fehlerhafte Zeile Nr. %ld: Fehler im Call",
  509.           ascii_filename, line_nr);
  510.       stop ("");
  511.     } else {
  512.       bp = bp2;
  513.     }
  514.     i = callcmp (prevcall, currcall) ;
  515.     if (i > 0) {
  516.       printf ("%s: Warnung in Zeile Nr. %ld: Zeile nicht in Sortierreihenfolge\n",
  517.           ascii_filename, line_nr);
  518.       sorted = 0;
  519.     }
  520.     if (i == 0) {
  521.       printf ("%s: Fehlerhafte Zeile Nr. %ld: Doppelter Digi %s",
  522.           ascii_filename, line_nr, stripcall (currcall));
  523.       stop ("");
  524.     }
  525.     if (!sorted) {
  526.       int i;
  527.       for (i = 0; i < d; i ++) {
  528.     if (!callcmp (digi (i) -> call, currcall)) {
  529.       printf ("%s: Fehlerhafte Zeile Nr. %ld: Doppelter Digi %s",
  530.           ascii_filename, line_nr, stripcall (currcall));
  531.       stop ("");
  532.     }
  533.       }
  534.     }
  535.     /* Call eingelesen -- umkopieren */
  536.     for (i = 0; i < 7; i ++) dt -> call [i] = prevcall [i] = currcall [i];
  537.     while (*bp && iswhitespace (*bp)) bp ++;
  538.     if (*bp != ',') {
  539.       printf ("%s: Fehlerhafte Zeile Nr. %ld",
  540.           ascii_filename, line_nr);
  541.       stop ("");
  542.     }
  543.     bp ++;
  544.     /* Locator */
  545.     while (*bp && iswhitespace (*bp)) bp ++;
  546.     if (*bp == ',') {
  547.       dt -> laenge = -1;
  548.       dt -> breite = -1;
  549.     } else {
  550.       if (strlen (bp) < 6) {
  551.     printf ("%s: Fehlerhafte Zeile Nr. %ld",
  552.         ascii_filename, line_nr);
  553.     stop ("");
  554.       }
  555.       for (i = 0; i < 6; i ++) {
  556.     if (bp [i] >= 'a' && bp [i] <= 'z')
  557.       bp [i] -= 32;
  558.       }
  559.       if (bp [0] < 'A' || bp [0] > 'R' ||
  560.       bp [1] < 'A' || bp [1] > 'R' ||
  561.       bp [2] < '0' || bp [2] > '9' ||
  562.       bp [3] < '0' || bp [3] > '9' ||
  563.       bp [4] < 'A' || bp [4] > 'X' ||
  564.       bp [5] < 'A' || bp [5] > 'X') {
  565.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Fehler im Locator",
  566.         ascii_filename, line_nr);
  567.     stop ("");
  568.       }
  569.       dt -> laenge = (bp [0] - 'A') * 240 +
  570.                  (bp [2] - '0') * 24 +
  571.                  (bp [4] - 'A');
  572.       dt -> breite = (bp [1] - 'A') * 240 +
  573.                      (bp [3] - '0') * 24 +
  574.              (bp [5] - 'A');
  575.       bp += 6;
  576.       while (*bp && iswhitespace (*bp)) bp ++;
  577.     }
  578.     if (*bp != ',') {
  579.       printf ("%s: Fehlerhafte Zeile Nr. %ld",
  580.           ascii_filename, line_nr);
  581.       stop ("");
  582.     }
  583.     bp ++;
  584.     /* Typ */
  585.     while (*bp && iswhitespace (*bp)) bp ++;
  586.     dt -> type = 0;
  587.     while (*bp >= '0' && *bp <= '9') {
  588.       dt -> type *= 10;
  589.       dt -> type += *bp - '0';
  590.       bp ++;
  591.     }
  592.     if (dt -> type != TYPE_USER && dt -> type != TYPE_SATG &&
  593.     dt -> type != TYPE_BBS  && dt -> type != TYPE_DIGI &&
  594.     dt -> type != TYPE_CLU  && dt -> type != TYPE_WX   &&
  595.     dt -> type != TYPE_TCP  && dt -> type != TYPE_TNC     ) {
  596.       printf ("%s: Fehlerhafte Zeile Nr. %ld: Unbekannter Typ",
  597.           ascii_filename, line_nr);
  598.       stop ("");
  599.     }
  600.     while (*bp && iswhitespace (*bp)) bp ++;
  601.     if (*bp != ',') {
  602.       printf ("%s: Fehlerhafte Zeile Nr. %ld",
  603.           ascii_filename, line_nr);
  604.       stop ("");
  605.     }
  606.     bp ++;
  607.     /* QRG */
  608.     while (*bp && iswhitespace (*bp)) bp ++;
  609.     if (*bp == ',') {
  610.       dt -> qrg = -1;
  611.     } else {
  612.       dt -> qrg = 0;
  613.       while (*bp >= '0' && *bp <= '9') {
  614.     dt -> qrg *= 10;
  615.     dt -> qrg += *bp - '0';
  616.     bp ++;
  617.       }
  618.       dt -> qrg *= 1000;
  619.       if (*bp == '.') {
  620.     bp ++;
  621.     i = 1000;
  622.     while (*bp >= '0' && *bp <= '9') {
  623.       if (i == 1) {
  624.         if (*bp >= '5') dt -> qrg ++;
  625.         i = 0;
  626.       } else {
  627.         i /= 10;
  628.         dt -> qrg += i * (*bp - '0');
  629.       }
  630.       bp ++;
  631.     }
  632.       }
  633.       while (*bp && iswhitespace (*bp)) bp ++;
  634.     }
  635.     if (*bp != ',') {
  636.       printf ("%s: Fehlerhafte Zeile Nr. %ld",
  637.           ascii_filename, line_nr);
  638.       stop ("");
  639.     }
  640.     bp ++;
  641.     /* Dummy */
  642.     while (*bp && *bp != ',') bp ++;
  643.     if (*bp != ',') {
  644.       printf ("%s: Fehlerhafte Zeile Nr. %ld",
  645.           ascii_filename, line_nr);
  646.       stop ("");
  647.     }
  648.     bp ++;
  649.     /* Links -- nur zaehlen */
  650.     while (*bp && iswhitespace (*bp)) bp ++;
  651.     if (*bp != '(') {
  652.       printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  653.       stop ("");
  654.     }
  655.     bp ++;
  656.     dt -> num_links = 0;
  657.     while (1) {
  658.       while (*bp && iswhitespace (*bp)) bp ++;
  659.       if (!*bp) {
  660.     printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  661.     stop ("");
  662.       }
  663.       if (*bp == ')') break;
  664.       if (dt -> num_links == 255) {
  665.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Zu viele Links",
  666.         ascii_filename, line_nr);
  667.     stop ("");
  668.       }
  669.       dt -> num_links ++;
  670.       while (*bp && *bp != ',' && *bp != ')') bp ++;
  671.       if (*bp == ',') bp ++;
  672.     }
  673.     bp ++; /* ) ueberspringen */
  674.     dt -> links = l;
  675.     l += dt -> num_links;
  676.     while (*bp && iswhitespace (*bp)) bp ++;
  677.     if (*bp != ',') {
  678.       printf ("%s: Fehlerhafte Zeile Nr. %ld",
  679.           ascii_filename, line_nr);
  680.       stop ("");
  681.     }
  682.     bp ++;
  683.     /* Info kopieren, max. 64 Zeichen... */
  684.     while (*bp && iswhitespace (*bp)) bp ++;
  685.     {
  686.       int whitespace = 0;
  687.       char info [MAXINFO];
  688.       i = 0;
  689.       while (*bp && i < MAXINFO) {
  690.     if (iswhitespace (*bp)) {
  691.       if (!whitespace) {
  692.         whitespace = 1;
  693.         info [i ++] = *bp;
  694.       }
  695.     } else {
  696.       whitespace = 0;
  697.       info [i ++] = *bp;
  698.     }
  699.     bp ++;
  700.       }
  701.       while (i && iswhitespace (info [i - 1])) i --;
  702.       while (i < MAXINFO) info [i ++] = 0;
  703.       if (fwrite (info, sizeof (char), MAXINFO, tmp_file) != MAXINFO)
  704.     pstop (tmpname);
  705.     }
  706.   }
  707.   if (fseek (ascfile, 0, 0)) pstop (ascii_filename);
  708. }
  709. void load_links ()
  710. {
  711.   DIGI_T *dt;
  712.   LINK_T *lt;
  713.   int d, l, i, j;
  714.   char *bp, *bp2;
  715.   char buf [2048];
  716.   long line_nr;
  717.   char call [7];
  718.   int neighbour, last_neighbour;
  719.  
  720.   line_nr = d = 0;
  721.   while (fgets (buf, 2048, ascfile)) {
  722.     last_neighbour = -1;
  723.     line_nr ++;
  724.     buf [2047] = 0;
  725.     for (bp = buf; *bp && iswhitespace (*bp); bp ++)
  726.       ;
  727.     if (!*bp || *bp == '#') continue;
  728.     dt = digi (d);
  729.     d ++;
  730.     for (i = 0; i < 5; i ++) {
  731.       while (*bp && *bp != ',') bp ++;
  732.       if (!*bp) {
  733.     printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  734.     stop ("");
  735.       }
  736.       bp ++;
  737.     }
  738.     while (*bp && iswhitespace (*bp)) bp ++;
  739.     if (*bp != '(') {
  740.       printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  741.       stop ("");
  742.     }
  743.     bp ++;
  744.     /* Links eintragen */
  745.     i = dt -> num_links;
  746.     l = dt -> links;
  747.     while (1) {
  748.       while (*bp && iswhitespace (*bp)) bp ++;
  749.       if (!*bp) {
  750.     printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  751.     stop ("");
  752.       }
  753.       if (*bp == ')') break;
  754.       if (!i) {
  755.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Falsche Linkangabe(n)",
  756.         ascii_filename, line_nr);
  757.     stop ("");
  758.       }
  759.       i --;
  760.       lt = link (l);
  761.       l ++;
  762.       bp2 = parse_call (bp, call);
  763.       if (bp2 == bp) {
  764.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Fehler im Linkpartner",
  765.         ascii_filename, line_nr);
  766.     stop ("");
  767.       } else {
  768.     bp = bp2;
  769.       }
  770.       if (!callcmp (call, dt -> call)) {
  771.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Link vom Digi zu sich selbst",
  772.         ascii_filename, line_nr);
  773.     stop ("");
  774.       }
  775.       neighbour = search_digi (call);
  776.       if (neighbour < 0) {
  777.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Unbekannter Linkpartner %s",
  778.         ascii_filename, line_nr, stripcall (call));
  779.     stop ("");
  780.       }
  781.       if (neighbour < last_neighbour) {
  782.     printf ("%s: Warnung in Zeile Nr. %ld: Links nicht sortiert\n",
  783.         ascii_filename, line_nr);
  784.       }
  785.       if (neighbour == last_neighbour) {
  786.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Doppelter Linkeintrag",
  787.         ascii_filename, line_nr);
  788.     stop ("");
  789.       }
  790.       for (j = dt -> links; j < l - 1; j ++) {
  791.     if (link (j) -> neighbour == neighbour) {
  792.       printf ("%s: Fehlerhafte Zeile Nr. %ld: Doppelter Linkeintrag",
  793.           ascii_filename, line_nr);
  794.       stop ("");
  795.     }
  796.       }
  797.       last_neighbour = neighbour;
  798.       lt -> neighbour = neighbour;
  799.       while (*bp && iswhitespace (*bp)) bp ++;
  800.       switch (*bp) {
  801.       case SYM_WIRE:
  802.     bp ++;
  803.     lt -> pquality = P_WIRE;
  804.     break;
  805.       case SYM_38K4:
  806.     bp ++;
  807.     lt -> pquality = P_38K4;
  808.     break;
  809.       case SYM_19K2:
  810.     bp ++;
  811.     lt -> pquality = P_19K2;
  812.     break;
  813.       case SYM_9K6:
  814.     bp ++;
  815.     lt -> pquality = P_9K6;
  816.     break;
  817.       case SYM_4K8:
  818.     bp ++;
  819.     lt -> pquality = P_4K8;
  820.     break;
  821.       case SYM_2K4:
  822.     bp ++;
  823.     lt -> pquality = P_2K4;
  824.     break;
  825.       case ',':
  826.       case ')':
  827.     /* Sonderbehandlung: Das Zeichen fuer 1K2 ist das nichtvorhandensein
  828.        eines Zeichens... :-)
  829.      */
  830.     lt -> pquality = P_1K2;
  831.     break;
  832.       case SYM_300:
  833.     bp ++;
  834.     lt -> pquality = P_300;
  835.     break;
  836.       case SYM_NONE:
  837.     bp ++;
  838.     lt -> pquality = P_NONE;
  839.     break;
  840.       default:
  841.     printf ("%s: Fehlerhafte Zeile Nr. %ld: Falsches Linksymbol",
  842.         ascii_filename, line_nr);
  843.     stop ("");
  844.       }
  845.       while (*bp && iswhitespace (*bp)) bp ++;
  846.       if (*bp != ',' && *bp != ')') {
  847.     printf ("%s: Fehlerhafte Zeile Nr. %ld",
  848.         ascii_filename, line_nr);
  849.     stop ("");
  850.       }
  851.       /*while (*bp && *bp != ',' && *bp != ')') bp ++;*/
  852.       if (*bp == ',') bp ++;
  853.     }
  854.   }
  855. }
  856. void check_links ()
  857. {
  858.   int d;
  859.   int l;
  860.   int i, j, k;
  861.   int n;
  862.   DIGI_T *dt1, *dt2;
  863.   LINK_T *lt;
  864.   for (d = 0; d < digis; d ++) {
  865.     dt1 = digi (d);
  866.     i = dt1 -> num_links;
  867.     for (l = dt1 -> links; i; i --, l ++) {
  868.       lt = link (l);
  869.       n = lt -> neighbour;
  870.       dt2 = digi (n);
  871.       k = dt2 -> num_links;
  872.       for (j = dt2 -> links; k; j ++, k --) {
  873.     if (link (j) -> neighbour == d) break;
  874.       }
  875.       if (!k) {
  876.     printf ("%s", stripcall (dt1 -> call));
  877.     printf (" --> %s besitzt keinen Rueckweg", stripcall (dt2 -> call));
  878.     stop ("");
  879.       }
  880.       if (link (j) -> pquality != lt -> pquality) {
  881.     printf ("%s", stripcall (dt1 -> call));
  882.     printf (" <--> %s hat verschieden schnelle Wege",
  883.         stripcall (dt2 -> call));
  884.     stop ("");
  885.       }
  886.     }
  887.   }
  888. }
  889. void countasc (digis, links)
  890. int *digis, *links;
  891. {
  892.   int d, l;
  893.   char buf [2048];
  894.   char *bp;
  895.   long line_nr;
  896.   line_nr=0;
  897.   l = d = 0;
  898.   while (fgets (buf, 2048, ascfile)) {
  899.     line_nr ++;
  900.     buf [2047] = 0;
  901.     for (bp = buf; *bp && iswhitespace (*bp); bp ++)
  902.       ;
  903.     if (*bp && *bp != '#') {
  904.       int c;
  905.       d ++;
  906.       for (c = 0; c < 5; c ++) {
  907.     while (*bp && *bp != ',') bp ++;
  908.     if (!*bp) {
  909.       printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  910.       stop ("");
  911.     }
  912.     bp ++;
  913.       }
  914.       while (*bp && iswhitespace (*bp)) bp ++;
  915.       if (*bp != '(') {
  916.     printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  917.     stop ("");
  918.       }
  919.       bp ++;
  920.       /* Links zaehlen */
  921.       while (1) {
  922.     while (*bp && iswhitespace (*bp)) bp ++;
  923.     if (!*bp) {
  924.       printf ("%s: Fehlerhafte Zeile Nr. %ld", ascii_filename, line_nr);
  925.       stop ("");
  926.     }
  927.     if (*bp == ')') break;
  928.     l ++;
  929.     while (*bp && *bp != ',' && *bp != ')') bp ++;
  930.     if (*bp == ',') bp ++;
  931.       }
  932.     }
  933.   }
  934.   *digis = d;
  935.   *links = l;
  936.   if (fseek (ascfile, 0, 0)) pstop (ascii_filename);
  937. }
  938. int callcmp (call1, call2)
  939. char *call1, *call2;
  940. {
  941.   int i;
  942.   for (i = 0; i < 7; i ++) {
  943.     if (call1 [i] > call2 [i]) return 1;
  944.     if (call1 [i] < call2 [i]) return -1;
  945.   }
  946.   return 0;
  947. }
  948. void printcoord (laenge, breite)
  949. int laenge, breite;
  950. {
  951.   int gr_nord, min_nord, sued_p;
  952.   int gr_ost, min_ost, west_p;
  953.   gr_nord = -90 + breite / 24;
  954.   min_nord = gr_nord * 60 + ((breite % 24) * 5) / 2;
  955.   sued_p=min_nord<0;
  956.   if(sued_p){
  957.     min_nord=-min_nord;
  958.     if(min_nord%5){
  959.       if(min_nord%5==3)min_nord--;
  960.     }
  961.   }
  962.   gr_ost = -180 + laenge / 12;
  963.   min_ost= gr_ost * 60 + (laenge % 12) * 5;
  964.   west_p=min_ost<0;
  965.   if(west_p){
  966.     min_ost=-min_ost;
  967.   }
  968.   printf ("%d Grad, %d", min_nord / 60 , min_nord % 60);
  969.   if (min_nord % 5) printf (".5");
  970.   printf(" Minuten %s, %d Grad, %d Minuten %s",
  971.      (sued_p?"Sued":"Nord"), min_ost/60, min_ost%60,
  972.      (west_p?"West":"Ost"));
  973. }
  974. void read_info (buf, index)
  975. char *buf;
  976. int index;
  977. {
  978.   if (fseek (binfile, (long) info_offset + MAXINFO * (long) index, 0))
  979.     pstop (bin_filename);
  980.   if (fread (buf, sizeof (char), MAXINFO, binfile) != 64)
  981.     pstop (bin_filename);
  982.   buf [MAXINFO] = 0;
  983. }
  984. char *asctype (nr)
  985. int nr;
  986. {
  987.   switch (nr) {
  988.   case TYPE_USER:
  989.     return "User";
  990.   case TYPE_SATG:
  991.     return "SAT ";
  992.   case TYPE_BBS:
  993.     return "BBS ";
  994.   case TYPE_DIGI:
  995.     return "Digi";
  996.   case TYPE_CLU:
  997.     return "DXCl";
  998.   case TYPE_WX:
  999.     return "WX  ";
  1000.   case TYPE_TCP:
  1001.     return "TCP ";
  1002.   case TYPE_TNC:
  1003.     return "TNC ";
  1004.   default:
  1005.     stop ("Unbekannter Knotentyp");
  1006.     return 0;
  1007.   }
  1008. }
  1009. char *vasctype (nr)
  1010. int nr;
  1011. {
  1012.   switch (nr) {
  1013.   case TYPE_USER:
  1014.     return "User";
  1015.   case TYPE_SATG:
  1016.     return "SAT-Gate";
  1017.   case TYPE_BBS:
  1018.     return "BBS";
  1019.   case TYPE_DIGI:
  1020.     return "Digipeater";
  1021.   case TYPE_CLU:
  1022.     return "DX-Cluster";
  1023.   case TYPE_WX:
  1024.     return "Wetterstation";
  1025.   case TYPE_TCP:
  1026.     return "TCP/IP-Knoten";
  1027.   case TYPE_TNC:
  1028.     return "Link-TNC";
  1029.   default:
  1030.     stop ("Unbekannter Knotentyp");
  1031.     return 0;
  1032.   }
  1033. }
  1034. char *asccall (call)
  1035. char call [7];
  1036. {
  1037.   static char asc [10];
  1038.   int i;
  1039.   for (i = 0; i < 6 && call [i] != ' '; i++) {
  1040.     asc [i] = call [i];
  1041.   }
  1042.   if (call [6]) {
  1043.     asc [i ++] = '-';
  1044.     if (call [6] > 9) asc [i ++] = '1';
  1045.     asc [i ++] = '0' + call [6] % 10;
  1046.   }
  1047.   while (i<9) asc [i ++] = ' ';
  1048.   asc [i] = 0;
  1049.   return asc;
  1050. }
  1051. char *stripstr (text)
  1052. char *text;
  1053. {
  1054.   char *str = text;
  1055.   while (*str && !iswhitespace (*str)) str ++;
  1056.   *str = 0;
  1057.   return text;
  1058. }
  1059. char *stripcall (call)
  1060. char call [7];
  1061. {
  1062.   return stripstr (asccall (call));
  1063. }
  1064. void printloc (laenge, breite)
  1065. short laenge, breite;
  1066. {
  1067.   printf ("%c%c%c%c%c%c", 'A' + laenge / 240, 'A' + breite / 240,
  1068.       '0' + (laenge / 24) % 10, '0' + (breite / 24) % 10,
  1069.       'A' + laenge % 24, 'A' + breite % 24);
  1070. }
  1071. void vausgabe(index)
  1072. int index;
  1073. {
  1074.   DIGI_T *x;
  1075.   char *call;
  1076.   char info [MAXINFO + 1];
  1077.   int i;
  1078.   int infocolumns;
  1079.  
  1080.   x = digi (index);
  1081.   call = stripcall (x -> call);
  1082.   printf ("Call: %s\n", call);
  1083.   printf ("Locator: ");
  1084.   if (x -> laenge < 0 || x -> breite < 0) {
  1085.     printf ("unbekannt");
  1086.   } else {
  1087.     printloc (x -> laenge, x -> breite);
  1088.     printf (" = ");
  1089.     printcoord (x -> laenge, x -> breite);
  1090.   }
  1091.   if (x -> qrg < 0) {
  1092.     printf ("\nQRG: unbekannt\nTyp: %s\n", vasctype (x -> type));
  1093.   } else {
  1094.     printf ("\nQRG: %4ld.%03ld\nTyp: %s\n", x -> qrg / 1000, x -> qrg % 1000,
  1095.         vasctype (x -> type));
  1096.   }
  1097.   read_info (info, index);
  1098.   infocolumns = COLUMNS - 6;
  1099.   if (infocolumns > MAXINFO) infocolumns = MAXINFO;
  1100.   info [infocolumns] = 0;
  1101.   printf ("Info: %s\n", info);
  1102.   if (x -> num_links) {
  1103.     LINK_T *l;
  1104.     printf ("Links:\n");
  1105.     for (i = 0; i < x -> num_links; i ++){
  1106.       l = link (x -> links + i);
  1107.       printf ("    %s  ", asccall (digi (l -> neighbour) -> call));
  1108.       switch (l -> pquality) {
  1109.       case P_WIRE:
  1110.     printf (NAME_WIRE);
  1111.     break;
  1112.       case P_38K4:
  1113.     printf (NAME_38K4);
  1114.     break;
  1115.       case P_19K2:
  1116.     printf (NAME_19K2);
  1117.     break;
  1118.       case P_9K6:
  1119.     printf (NAME_9K6);
  1120.     break;
  1121.       case P_4K8:
  1122.     printf (NAME_4K8);
  1123.     break;
  1124.       case P_2K4:
  1125.     printf (NAME_2K4);
  1126.     break;
  1127.       case P_1K2:
  1128.     printf (NAME_1K2);
  1129.     break;
  1130.       case P_300:
  1131.     printf (NAME_300);
  1132.     break;
  1133.       case P_NONE:
  1134.     printf (NAME_NONE);
  1135.     break;
  1136.       default:
  1137.     stop ("Unbekannter Linktyp");
  1138.       }
  1139.       printf("\n");
  1140.     }
  1141.   }
  1142. }
  1143. void ausgabe(index)
  1144. int index;
  1145. {
  1146.   DIGI_T *x;
  1147.   char info [MAXINFO + 1];
  1148.   int infocolumns;
  1149.   x = digi(index);
  1150.   printf ("%s", asccall (x -> call));
  1151.   printf (" ");
  1152.   if (x -> laenge < 0 || x -> breite < 0) {
  1153.     printf ("      ");
  1154.   } else {
  1155.     printloc (x -> laenge, x -> breite);
  1156.   }
  1157.   if (x -> qrg < 0) {
  1158.     printf ("          ");
  1159.   } else {
  1160.     printf (" %4ld.%03ld ", x -> qrg / 1000, x -> qrg % 1000);
  1161.   }
  1162.   printf ("%s", asctype (x -> type));
  1163.   printf (" %2d  ", x -> num_links);
  1164.   /* Info einlesen */
  1165.   read_info (info, index);
  1166.   infocolumns = COLUMNS - 35;
  1167.   if (infocolumns > MAXINFO) infocolumns = MAXINFO;
  1168.   info [infocolumns] = 0;
  1169.   printf ("%s\n", info);
  1170. }
  1171. void compile_data()
  1172. {
  1173. #ifdef UNIX
  1174.   sprintf (tmpname, INFO_TMP, getpid ());
  1175. #else
  1176.   strcpy (tmpname, INFO_TMP);
  1177. #endif
  1178.   printf ("Compilieren der Daten...\n");
  1179.   if ((ascfile = fopen (ascii_filename, "r")) == 0) pstop (ascii_filename);
  1180. #ifdef DEBUG
  1181.   printf ("Schritt 1\n");
  1182. #endif
  1183.   countasc (&digis, &links);
  1184. #ifdef DEBUG
  1185.   printf ("%d Digis, %d Links\nSchritt 2\n", digis, links);
  1186. #endif
  1187.   alloc (digis, links);
  1188.   if ((tmp_file = fopen (tmpname, "wb")) == 0) pstop (tmpname);
  1189.   tmp_exists = 1;
  1190.   load_digis ();
  1191.   if (fclose (tmp_file) == EOF) pstop (tmpname);
  1192. #ifdef DEBUG
  1193.   printf ("Schritt 3\n");
  1194. #endif
  1195.   load_links ();
  1196. #ifdef DEBUG
  1197.   printf ("Schritt 4\n");
  1198. #endif
  1199.   check_links ();
  1200.   if ((binfile = fopen (bin_filename, "wb")) == 0) pstop (bin_filename);
  1201.   if ((tmp_file = fopen (tmpname, "rb")) == 0) pstop (tmpname);
  1202.   dump ();
  1203.   if (fclose (tmp_file) == EOF) pstop (tmpname);
  1204.   tmp_exists = 0;
  1205.   if (unlink (tmpname)) pstop (tmpname);
  1206.   free_data ();
  1207.   printf ("\n");
  1208.   if (fclose (ascfile) == EOF) pstop (ascii_filename);
  1209. }
  1210. void data_info()
  1211. {
  1212.   long version, digis, links;
  1213.   int sorted;
  1214.   if((binfile = fopen(bin_filename, "rb")) == NULL) pstop(bin_filename);
  1215.   if(get_numl(binfile, &version, 2) != 2) pstop(bin_filename);
  1216.   sorted = (version & 0x8000) != 0;
  1217.   version &= 0x7fff;
  1218.   if(get_numl(binfile, &digis, 2) != 2) pstop(bin_filename);
  1219.   if(get_numl(binfile, &links, 2) != 2) pstop(bin_filename);
  1220.   printf("Datenfile %s\n", bin_filename);
  1221.   printf("Version %2ld.%01ld%01ld (%s), ", (version>>8)&255, (version>>4)&15,
  1222.      version&15, sorted ? "sortiert" : "unsortiert");
  1223.   printf("%ld Digis, %ld Links\n\n", digis, links);
  1224.   if (fclose (binfile) == EOF) pstop (bin_filename);
  1225. }
  1226. void load_data()
  1227. {
  1228.   long version;
  1229.   int i;
  1230.   long tmp;
  1231.   if(asciinewer()){
  1232.     compile_data();
  1233.   }
  1234.   if((binfile = fopen(bin_filename,"rb")) == NULL) {
  1235.     pstop(bin_filename);
  1236.   }
  1237.   if(get_numl(binfile, &version, 2) != 2) pstop(bin_filename);
  1238.   sorted = (version & 0x8000) != 0;
  1239.   version &= 0x7fff;
  1240.   if(version>FILEVERS){
  1241.     printf("%s", bin_filename);
  1242.     stop(": Unbekannte Version");
  1243.   }
  1244.   if(get_numl(binfile,&tmp,2) != 2) pstop(bin_filename);
  1245.   digis = (int) tmp;
  1246.   if(get_numl(binfile,&tmp,2) != 2) pstop(bin_filename); 
  1247.   links = (int) tmp;
  1248.   if((long) digis > 32767 || (long) links > 32767){
  1249.     printf("%s", bin_filename);
  1250. #ifdef DEBUG
  1251.     stop(": digis>32767 || links>32767");
  1252. #else
  1253.     stop(": Fehlerhafte Datei");
  1254. #endif
  1255.   }
  1256.   if(fseek(binfile, 0l, 2)) pstop(bin_filename);
  1257.   if(ftell(binfile) != 6l + (long) digis*(FILE_DIGI_T_LENGTH+MAXINFO) +
  1258.                        (long) links*FILE_LINK_T_LENGTH){
  1259.     printf("%s", bin_filename);
  1260. #ifdef DEBUG
  1261.     stop(": Falsche Dateilaenge");
  1262. #else
  1263.     stop(": Fehlerhafte Datei");
  1264. #endif
  1265.   }
  1266.   if(fseek(binfile, 6l, 0)) pstop(bin_filename);
  1267.   alloc (digis, links);
  1268.   /* Digis laden */
  1269.   for(i=0;i<digis;i++){
  1270.     if(fread(digi(i)->call, sizeof(char), 7, binfile) != 7)
  1271.       pstop(bin_filename);
  1272.     if(get_numl(binfile, &tmp, 2) != 2) pstop(bin_filename);
  1273.     digi(i)->laenge = tmp;
  1274.     if(tmp>(360*12) && tmp != 0x0000ffffl){
  1275.       printf("%s", bin_filename);
  1276. #ifdef DEBUG
  1277.       stop(": laenge");
  1278. #else
  1279.       stop(": Fehlerhafte Datei");
  1280. #endif
  1281.     }
  1282.     if(get_numl(binfile, &tmp, 2) != 2) pstop(bin_filename);
  1283.     digi(i)->breite = tmp;
  1284.     if(tmp>(180*24) && tmp != 0x0000ffffl){
  1285.       printf("%s", bin_filename);
  1286. #ifdef DEBUG
  1287.       stop(": breite");
  1288. #else
  1289.       stop(": Fehlerhafte Datei");
  1290. #endif
  1291.     }
  1292.     if(get_numl(binfile, &tmp, 2) != 2) pstop(bin_filename);
  1293.     digi(i)->type = tmp;
  1294.     if (tmp != TYPE_USER && tmp != TYPE_SATG &&
  1295.     tmp != TYPE_BBS  && tmp != TYPE_DIGI &&
  1296.     tmp != TYPE_CLU  && tmp != TYPE_WX   &&
  1297.     tmp != TYPE_TCP  && tmp != TYPE_TNC     ){
  1298.       printf("%s", bin_filename);
  1299. #ifdef DEBUG
  1300.       stop(": type");
  1301. #else
  1302.       stop(": Fehlerhafte Datei");
  1303. #endif
  1304.     }
  1305.     if(get_numl(binfile, &tmp, 4) != 4) pstop(bin_filename);
  1306.     digi(i)->qrg = tmp;
  1307.     if(get_numl(binfile, &tmp, 1) != 1) pstop(bin_filename);
  1308.     digi(i)->num_links = tmp;
  1309.     if(tmp>links){
  1310.       printf("%s", bin_filename);
  1311. #ifdef DEBUG
  1312.       stop(": num_links");
  1313. #else
  1314.       stop(": Fehlerhafte Datei");
  1315. #endif
  1316.     }
  1317.     if(get_numl(binfile, &tmp, 2) != 2) pstop(bin_filename);
  1318.     digi(i)->links = tmp;
  1319.     if(tmp+digi(i)->num_links > links){
  1320.       printf("%s", bin_filename);
  1321. #ifdef DEBUG
  1322.       stop(": links+num_links > links gesamt");
  1323. #else
  1324.       stop(": Fehlerhafte Datei");
  1325. #endif
  1326.     }
  1327.   }
  1328.   for(i=0; i<links; i++){
  1329.     if(get_numl(binfile, &tmp, 2) != 2) pstop(bin_filename);
  1330.     link(i)->neighbour = tmp;
  1331.     if(tmp >= digis){
  1332.       printf("%s", bin_filename);
  1333. #ifdef DEBUG
  1334.       stop(": neighbour");
  1335. #else
  1336.       stop(": Fehlerhafte Datei");
  1337. #endif
  1338.     }
  1339.     if(get_numl(binfile, &tmp, 2) != 2) pstop(bin_filename);
  1340.     link(i)->pquality = tmp;
  1341.   }
  1342.   info_offset=ftell(binfile);
  1343. }
  1344. void find_qrg(qrgstr)
  1345. char *qrgstr;
  1346. {
  1347.   /* Lineares Durchsuchen der Digi-Liste... */
  1348.   int i;
  1349.   long qrg;
  1350.   int found;
  1351.   printf("Call       Loc      QRG   Typ  Lks Info\n");
  1352.   /* Zuerst parsen der qrg... */
  1353.   qrg=0;
  1354.   while (*qrgstr && iswhitespace(*qrgstr)) qrgstr++;
  1355.   qrg=0;
  1356.   while (*qrgstr && *qrgstr>='0' && *qrgstr<='9') {
  1357.     qrg *= 10;
  1358.     qrg += *qrgstr - '0';
  1359.     qrgstr ++;
  1360.   }
  1361.   qrg *= 1000; /* Das waren die MHz */
  1362.   /* Nun ist ein Dezimalpunkt erlaubt. */
  1363.   if (*qrgstr == '.') {
  1364.     int faktor=1000;
  1365.     /* Kilohertz einlesen */
  1366.     qrgstr ++;
  1367.     while (*qrgstr >= '0' && *qrgstr <= '9') {
  1368.       if (faktor==1) {
  1369.     /* Runden */
  1370.     if (*qrgstr >= '5') qrg++;
  1371.     break;
  1372.       } else {
  1373.     faktor /= 10;
  1374.     qrg += faktor * (*qrgstr - '0');
  1375.       }
  1376.       qrgstr ++;
  1377.     }
  1378.   }
  1379.   found = 0;
  1380.   for (i = 0; i < digis; i ++) {
  1381.     if (digi(i) -> qrg == qrg) {
  1382.       ausgabe(i);
  1383.       found ++;
  1384.     }
  1385.   }
  1386.   if (!found) {
  1387.     printf("\nKein Digi mit der angegebenen QRG gefunden.\n\n");
  1388.   } else {
  1389.     if (found == 1) {
  1390.       printf ("\n1 Digi gefunden.\n\n");
  1391.     } else {
  1392.       printf("\n%d Digis gefunden.\n\n", found);
  1393.     }
  1394.   }
  1395. }
  1396. int info_call(callstr)
  1397. char *callstr;
  1398. /* Return: 0=OK, Call gefunden, sonst nicht gefunden */
  1399. {
  1400.   char call[7];
  1401.   int i;
  1402.   char *bp;
  1403.   /* Call parsen */
  1404.   bp = parse_call (callstr, call);
  1405.   if (bp == callstr) {
  1406.     stop ("Fehler in Rufzeichenangabe");
  1407.   } else {
  1408.     callstr = bp;
  1409.   }
  1410.   while (*callstr) {
  1411.     if (!iswhitespace (*callstr)) stop ("Fehler in Rufzeichenangabe");
  1412.     callstr ++;
  1413.   }
  1414.   i = search_digi (call);
  1415.   if (i < 0) {
  1416.     return 1;
  1417.   } else {
  1418.     vausgabe (i);
  1419.     printf ("\n");
  1420.     return 0;
  1421.   }
  1422. }
  1423. void info_prefix(prefix)
  1424. char *prefix;
  1425. {
  1426.   char pr[7];
  1427.   int i, found;
  1428.   int len;
  1429.   int header_printed = 0;
  1430.   char *bp;
  1431.   /* Prefix parsen */
  1432.   if (!*prefix) {
  1433.     /* Sonderfall: ALLE Digis listen */
  1434.     for (i = 0; i < 6; i ++) pr [i] = ' ';
  1435.     pr [6] = 0;
  1436.   } else {
  1437.     bp = parse_call (prefix, pr);
  1438.     if (bp == prefix) {
  1439.       stop ("Fehler in Rufzeichenangabe");
  1440.     } else {
  1441.       prefix = bp;
  1442.     }
  1443.     while (*prefix) {
  1444.       if (!iswhitespace (*prefix)) stop ("Fehler in Rufzeichenangabe");
  1445.       prefix ++;
  1446.     }
  1447.   }
  1448.   for (len = 0; len < 6 && pr [len] != ' '; len ++)
  1449.     ;
  1450.   found = 0;
  1451.   for (i = 0; i < digis; i ++) {
  1452.     int j; DIGI_T *d;
  1453.     d = digi (i);
  1454.     for (j = 0; j < len; j ++) {
  1455.       if (pr [j] != d -> call [j]) break;
  1456.     }
  1457.     if (j == len) {
  1458.       if (!header_printed) {
  1459.     printf("Call       Loc      QRG   Typ  Lks Info\n");
  1460.     header_printed = 1;
  1461.       }
  1462.       ausgabe (i);
  1463.       found ++;
  1464.     }
  1465.   }
  1466.   if (!found) {
  1467.     printf("Call/Praefix nicht gefunden.\n\n");
  1468.   } else {
  1469.     if (found == 1) {
  1470.       printf ("\n1 Digi gefunden.\n\n");
  1471.     } else {
  1472.       printf("\n%d Digis gefunden.\n\n", found);
  1473.     }
  1474.   }
  1475. }
  1476. void exclude_call (call, src, dest)
  1477. char call [7], src [7], dest [7];
  1478. {
  1479.   int d, d2, i, j, k, l;
  1480.   if (!callcmp (call, src)) stop ("Ausschluss des 1. Calls unmoeglich");
  1481.   if (!callcmp (call, dest)) stop ("Ausschluss des 2. Calls unmoeglich");
  1482.   d = search_digi (call);
  1483.   if (d < 0) {
  1484.     printf ("Digi %s nicht gefunden", stripcall (call));
  1485.     stop ("");
  1486.   }
  1487.   for (i = digi (d) -> links, j = i + digi(d) -> num_links;
  1488.        i < j; i ++) {
  1489.     link (i) -> pquality = infty;
  1490.     d2 = link (i) -> neighbour;
  1491.     for (k = digi (d2) -> links, l = k + digi (d2) -> num_links;
  1492.      k < l; k ++) {
  1493.       if (link (k) -> neighbour == d) {
  1494.     link (k) -> pquality = infty;
  1495.     break;
  1496.       }
  1497.     }
  1498.     if (k == l) stop ("Inkonsistenz in Datendatei");
  1499.   }
  1500. }
  1501. void exclude_link (call1, call2)
  1502. char call1 [7], call2 [7];
  1503. {
  1504.   int d1, d2, i, j;
  1505.   d1 = search_digi (call1);
  1506.   if (d1 < 0) {
  1507.     printf ("Digi %s nicht gefunden", stripcall (call1));
  1508.     stop ("");
  1509.   }
  1510.   d2 = search_digi (call2);
  1511.   if (d2 < 0) {
  1512.     printf ("Digi %s nicht gefunden", stripcall (call2));
  1513.     stop ("");
  1514.   }
  1515.   for (i = digi (d1) -> links, j = i + digi (d1) -> num_links;
  1516.        i < j; i ++) {
  1517.     if (link (i) -> neighbour == d2) {
  1518.       link (i) -> pquality = infty;
  1519.       break;
  1520.     }
  1521.   }
  1522.   if (i == j) {
  1523.     printf ("Link %s", stripcall (call1));
  1524.     printf ("/%s nicht gefunden", stripcall (call2));
  1525.     stop ("");
  1526.   }
  1527.   for (i = digi (d2) -> links, j = i + digi (d2) -> num_links;
  1528.        i < j; i ++) {
  1529.     if (link (i) -> neighbour == d1) {
  1530.       link (i) -> pquality = infty;
  1531.       break;
  1532.     }
  1533.   }
  1534.   if (i == j)
  1535.     stop ("Inkonsistenz in Datendatei");
  1536. }
  1537. void do_exclusions (num, list, src, dest)
  1538. int num;
  1539. char **list;
  1540. char *src, *dest;
  1541. {
  1542.   int i;
  1543.   char *bp1, *bp2;
  1544.   char call1 [7], call2 [7], srccall [7], destcall [7];
  1545.   bp1 = src;
  1546.   bp2 = parse_call (bp1, srccall);
  1547.   if (bp1 == bp2) stop ("Fehler im 1. Call");
  1548.   while (*bp2 && iswhitespace (*bp2)) bp2 ++;
  1549.   if (*bp2) stop ("Fehler im 1. Call");
  1550.   bp1 = dest;
  1551.   bp2 = parse_call (bp1, destcall);
  1552.   if (bp1 == bp2) stop ("Fehler im 2. Call");
  1553.   while (*bp2 && iswhitespace (*bp2)) bp2 ++;
  1554.   if (*bp2) stop ("Fehler im 2. Call");
  1555.   for (i = 0; i < num; i ++) {
  1556.     bp1 = list [i];
  1557.     bp2 = parse_call (bp1, call1);
  1558.     if (bp1 == bp2) stop ("Fehler im Ausschluss: Call falsch");
  1559.     bp1 = bp2;
  1560.     while (*bp1 && iswhitespace (*bp1)) bp1 ++;
  1561.     if (*bp1 && *bp1 != '/') stop ("Fehler im Ausschluss");
  1562.     if (*bp1 == '/') {
  1563.       bp1 ++;
  1564.       bp2 = parse_call (bp1, call2);
  1565.       if (bp2 == bp1) stop ("Fehler im Ausschluss: Call falsch");
  1566.       while (*bp2 && iswhitespace (*bp2)) bp2 ++;
  1567.       if (*bp2) stop ("Fehler im Ausschluss");
  1568.       exclude_link (call1, call2);
  1569.     } else {
  1570.       exclude_call (call1, srccall, destcall);
  1571.     }
  1572.   }
  1573. }
  1574. void print_quality (qual)
  1575. int qual;
  1576. {
  1577.   int percent;
  1578.   percent = 10000;
  1579.   if (qual < 0) internal (5, "qual < 0");
  1580.   while (qual >= 6) {
  1581.     percent = (int) ((99l * percent + 50l) / 100);
  1582.     qual -= 6;
  1583.   }
  1584.   if (qual >= 3) {
  1585.     percent = (int) ((199l * percent + 100l) / 200);
  1586.     qual -= 3;
  1587.   }
  1588.   while (qual > 0) {
  1589.     percent = (int) ((19966l * percent + 10000l) / 20000l);
  1590.     qual --;
  1591.   }
  1592.   printf ("Qualitaet: %d %%\n", (percent + 50) / 100);
  1593. }
  1594. void print_path (n, tab)
  1595. int n;
  1596. SEARCH_T *tab;
  1597. {
  1598.   int qual;
  1599.   printf ("Pfad: ");
  1600.   while (n) {
  1601.     if (n < 0) internal (4, "n < 0");
  1602.     printf ("%s", stripcall (digi (tab [n] . digi & 0x7fff) -> call));
  1603.     qual = tab [n] . pquality;
  1604.     n = tab [n] . neighbour;
  1605.     qual -= tab [n] . pquality;
  1606.     switch (qual) {
  1607.     case P_WIRE:
  1608.       printf ("%s", STR_WIRE);
  1609.       break;
  1610.     case P_38K4:
  1611.       printf ("%s", STR_38K4);
  1612.       break;
  1613.     case P_19K2:
  1614.       printf ("%s", STR_19K2);
  1615.       break;
  1616.     case P_9K6:
  1617.       printf ("%s", STR_9K6);
  1618.       break;
  1619.     case P_4K8:
  1620.       printf ("%s", STR_4K8);
  1621.       break;
  1622.     case P_2K4:
  1623.       printf ("%s", STR_2K4);
  1624.       break;
  1625.     case P_1K2:
  1626.       printf ("%s", STR_1K2);
  1627.       break;
  1628.     case P_300:
  1629.       printf ("%s", STR_300);
  1630.       break;
  1631.     case P_NONE:
  1632.       printf ("%s", STR_NONE);
  1633.       break;
  1634.     default:
  1635.       internal (3, "Pathtrace: Linktype");
  1636.     }
  1637.   }
  1638.   printf ("%s\n", stripcall (digi (tab [0].digi & 0x7fff) -> call));
  1639. }
  1640. void print_distances (n, tab)
  1641. int n;
  1642. SEARCH_T *tab;
  1643. {
  1644.   n = n; tab = tab;
  1645. }
  1646. void found_route (n, tab)
  1647. int n;
  1648. SEARCH_T *tab;
  1649. {
  1650.   printf ("Link gefunden:\n\n");
  1651.   print_quality (tab [n] . pquality);
  1652.   print_path (n, tab);
  1653.   print_distances (n, tab);
  1654.   printf ("\n");
  1655. }
  1656. void find_route(src,dest)
  1657. char *src, *dest;
  1658. {
  1659.   SEARCH_T *searchtab;
  1660.   int searched_digis;
  1661.   int w; /* Working digi */
  1662.   char srccall [7], destcall [7];
  1663.   char *bp;
  1664.   int dsrc, ddest;
  1665.   if ((searchtab = calloc (digis, sizeof (SEARCH_T))) == 0)
  1666.     stop ("Nicht genug Speicher");
  1667.   searched_digis = 0;
  1668.   bp = parse_call (src, srccall);
  1669.   if (bp == src) stop ("Fehler im 1. Call");
  1670.   while (*bp && iswhitespace (*bp)) bp ++;
  1671.   if (*bp) pstop ("Fehler im 1. Call");
  1672.   bp = parse_call (dest, destcall);
  1673.   if (bp == dest) stop ("Fehler im 2. Call");
  1674.   while (*bp && iswhitespace (*bp)) bp ++;
  1675.   if (*bp) pstop ("Fehler im 2. Call");
  1676.   dsrc = search_digi (srccall);
  1677.   if (dsrc < 0) {
  1678.     printf ("Digi %s nicht gefunden", stripcall (srccall));
  1679.     stop ("");
  1680.   }
  1681.   ddest = search_digi (destcall);
  1682.   if (ddest < 0) {
  1683.     printf ("Digi %s nicht gefunden", stripcall (destcall));
  1684.     stop ("");
  1685.   }
  1686.   searchtab [0].digi = ddest;
  1687.   searchtab [0].pquality = 0;
  1688.   searched_digis = 1;
  1689.   w = 0;
  1690.   while (1) {
  1691.     /* Algorithmus durchfuehren */
  1692.     {
  1693.       /* Vom Working Digi aus alle Links eintragen */
  1694.       int li, lj, si;
  1695.       unsigned int qual;
  1696.       qual = searchtab [w] . pquality;
  1697.       for (li = digi(searchtab [w] . digi & 0x7fff) -> links,
  1698.        lj = li + digi(searchtab [w] . digi & 0x7fff) -> num_links;
  1699.        li < lj; li ++) {
  1700.     if (qual + link (li) -> pquality >= infty) continue;
  1701.     for (si = 0; si < searched_digis; si ++) {
  1702.       if (searchtab [si] . digi == link (li) -> neighbour) {
  1703.         if (searchtab [si] . pquality > qual + link (li) -> pquality) {
  1704.           searchtab [si] . pquality = qual + link (li) -> pquality;
  1705.           searchtab [si] . neighbour = w;
  1706.         }
  1707.         break;
  1708.       }
  1709.       if ((searchtab [si] . digi & 0x7fff) == link (li) -> neighbour)
  1710.         break;
  1711.     }
  1712.     if (si == searched_digis) {
  1713.       /* Neu eintragen */
  1714.       searchtab [si] . digi = link (li) -> neighbour;
  1715.       searchtab [si] . pquality = qual + link (li) -> pquality;
  1716.       searchtab [si] . neighbour = w;
  1717.       searched_digis ++;
  1718.     }
  1719.       }
  1720.     }
  1721.     {
  1722.       /* Naechsten Working Digi bestimmen */
  1723.       int min_qual = infty;
  1724.       int wi;
  1725.       w = -1;
  1726.       for (wi = 0; wi < searched_digis; wi ++) {
  1727.     if ((searchtab [wi] . digi & 0x8000) == 0 &&
  1728.         searchtab [wi] . pquality < min_qual) {
  1729.       w = wi;
  1730.       min_qual = searchtab [wi] . pquality;
  1731.     }
  1732.       }
  1733.       if (min_qual == infty) {
  1734.     printf ("Kein Link zwischen %s", stripcall (srccall));
  1735.     printf (" und %s gefunden.\n\n", stripcall (destcall));
  1736.     return;
  1737.       }
  1738.       if (searchtab [w] . digi == dsrc) {
  1739.     found_route (w, searchtab);
  1740.     return;
  1741.       }
  1742.       searchtab [w] . digi |= 0x8000;
  1743.     }
  1744.   }
  1745. }
  1746.  
  1747. void stop(str)
  1748. char *str;
  1749. {
  1750.   printf("%s\n\n",str);
  1751.   if (tmp_exists) unlink (tmpname);
  1752.   exit(0);
  1753. }
  1754. void internal(num,str)
  1755. int num;
  1756. char *str;
  1757. {
  1758.   printf("Interner Fehler #%d: %s\n",num,str);
  1759.   printf("Bitte an dl6sdc mit Angabe des Rechnertyps, Betriebssystems,\n");
  1760.   printf("Programmversion, und woher Sie das Programm haben, usw. melden\n");
  1761.   printf("Dann wird der Fehler einigermassen schnell korrigiert :-)\n\n");
  1762.   if (tmp_exists) unlink (tmpname);
  1763.   exit(0);
  1764. }
  1765. void pstop(str)
  1766. char *str;
  1767. {
  1768.   perror(str);
  1769.   printf("\n");
  1770.   if (tmp_exists) unlink (tmpname);
  1771.   exit(0);
  1772. }
  1773. void parse_options(argc,argv)
  1774. int argc;
  1775. char **argv;
  1776. {
  1777. #if OPTIONS && defined (UNIX)
  1778.   extern char *optarg;
  1779.   char c;
  1780. #endif
  1781. #if OPTIONS || !defined(UNIX)
  1782.   ascii_filename=getenv("ASC_FILE");
  1783.   bin_filename=getenv("BIN_FILE");
  1784. #else
  1785.   ascii_filename=0;
  1786.   bin_filename=0;
  1787. #endif
  1788.   if( !ascii_filename || !*ascii_filename ) ascii_filename=ASCII_FILENAME;
  1789.   if( !bin_filename || !*bin_filename ) bin_filename=BIN_FILENAME;
  1790. #if OPTIONS && defined (UNIX)
  1791.   while((c=getopt(argc,argv,"a:b:h"))!=EOF){
  1792.     switch(c){
  1793.     case 'a':
  1794.       ascii_filename=optarg;
  1795.       break;
  1796.     case 'b':
  1797.       bin_filename=optarg;
  1798.       break;
  1799.     default:
  1800.       usage();
  1801.       exit(0);
  1802.     }
  1803.   }
  1804. #else
  1805.   argc = argc; argv = argv;
  1806. #endif
  1807. }
  1808. int asciinewer()
  1809. {
  1810.   struct stat statbuf;
  1811.   time_t asctime,bintime;
  1812.   int ascvalid,binvalid;
  1813.  
  1814.   if(stat(ascii_filename,&statbuf)){
  1815.     ascvalid=0;
  1816.   }else{
  1817.     ascvalid=1;
  1818.     asctime=statbuf.st_mtime;
  1819.   }
  1820.   if(stat(bin_filename,&statbuf)){
  1821.     binvalid=0;
  1822.   }else{
  1823.     binvalid=1;
  1824.     bintime=statbuf.st_mtime;
  1825.   }
  1826.   if(!ascvalid && !binvalid){
  1827.     stop("Datenfiles fehlen!");
  1828.   }
  1829.   if(!binvalid)return 1;
  1830.   if(!ascvalid)return 0;
  1831.   return asctime>=bintime;
  1832. }
  1833. int put_num(stream, num, bytes)
  1834. FILE *stream;
  1835. long num;
  1836. int bytes;
  1837. {
  1838.   int i;
  1839.   for(i=0;i<bytes;i++){
  1840.     if(putc((int) (num&255),stream)==EOF)return i;
  1841.     num>>=8;
  1842.   }
  1843.   return i;
  1844. }
  1845. int get_numl(stream, num, bytes)
  1846. FILE *stream;
  1847. long *num;
  1848. int bytes;
  1849. {
  1850.   int i,c;
  1851.   for(i=0,*num=0;i<bytes;i++){
  1852.     if((c=getc(stream))==EOF)return i;
  1853.     *num|=((long) c&255l)<<(8*i);
  1854.   }
  1855.   return i;
  1856. }
  1857. int iswhitespace(ch)
  1858. char ch;
  1859. {
  1860.   if(ch=='\t'||ch=='\n'||ch=='\r'||ch==' ')return 1;
  1861.   return 0;
  1862. }
  1863. void strtoupper(str)
  1864. char *str;
  1865. {
  1866.   while(*str){
  1867.     if(*str>='a'&&*str<='z')*str-=32;
  1868.     str++;
  1869.   }
  1870. }
  1871. int qthvalid(str)
  1872. char *str;
  1873. {
  1874.   strtoupper(str);
  1875.   while(iswhitespace(*str))str++;
  1876.   if(*str<'A'||*str>'R')return 0;
  1877.   str++;
  1878.   if(*str<'A'||*str>'R')return 0;
  1879.   str++;
  1880.   if(*str<'0'||*str>'9')return 0;
  1881.   str++;
  1882.   if(*str<'0'||*str>'9')return 0;
  1883.   str++;
  1884.   if(*str<'A'||*str>'X')return 0;
  1885.   str++;
  1886.   if(*str<'A'||*str>'X')return 0;
  1887.   str++;
  1888.   while(*str){
  1889.     if(!iswhitespace(*str))return 0;
  1890.     str++;
  1891.   }
  1892.   return 1;
  1893. }
  1894. int qrgvalid(str)
  1895. char *str;
  1896. {
  1897.   while(iswhitespace(*str))str++;
  1898.   while(*str&&!iswhitespace(*str)&&*str!='.'){
  1899.     if(*str<'0' || *str>'9') return 0;
  1900.     str++;
  1901.   }
  1902.   if(*str=='.'){
  1903.     str++;
  1904.     while(*str&&!iswhitespace(*str)){
  1905.       if(*str<'0' || *str>'9') return 0;
  1906.       str++;
  1907.     }
  1908.   }
  1909.   while(*str){
  1910.     if(!iswhitespace(*str)) return 0;
  1911.     str++;
  1912.   }
  1913.   return 1;
  1914. }
  1915. void copyright()
  1916. {
  1917. #ifdef DEBUG
  1918.   printf ("\n%s -- Debug-Version\n\n", VERSION);
  1919. #else
  1920.   printf("\n%s\n\n",VERSION);
  1921. #endif
  1922. }
  1923. void usage()
  1924. {
  1925. #if OPTIONS && defined (UNIX)
  1926.   printf("Anleitung: LINKINFO {Optionen} Befehl\n\n");
  1927.   printf("Optionen: -a <Ascii-Dateiname>   Waehlt den Namen der ASCII-Datei aus\n");
  1928.   printf("          -b <Bin-Dateiname>     Waehlt den Namen der internen Binaerdatei aus\n");
  1929.   printf("          -h                     Zeigt diese Hilfe an\n\n");
  1930. #else
  1931.   printf("Anleitung: LINKINFO Befehl\n\n");
  1932. #endif
  1933. #if OPTIONS
  1934.   printf("Standard:\n");
  1935.   printf("   ASCII=%s, Binaer=%s\n", ASCII_FILENAME, BIN_FILENAME);
  1936.   printf("Aktuelle Einstellung:\n");
  1937.   printf("   ASCII=%s, Binaer=%s\n\n", ascii_filename, bin_filename);
  1938. #endif
  1939.   printf("Befehl: <call>               Info ueber Call ausgeben\n");
  1940.   printf("        <praefix>            Calls zu Praefix ausgeben\n");
  1941.   printf("        <QRG>                Calls zu QRG ausgeben\n");
  1942.   printf("        <Locator>            Locator in Grad umrechnen\n");
  1943.   printf("        <1> <2> {Ausschluss} Pfad zwischen <1> und <2> mit Ausschluessen\n\n");
  1944.   printf("Ausschluss: Nahezu beliebig viele Angaben der folgenden Art:\n");
  1945.   printf("        <call>          Route nicht ueber call\n");
  1946.   printf("        <call1>/<call2> (Schraegstrich, aber KEIN Leerzeichen dazwischen)\n");
  1947.   printf("                        Nicht ueber den Link call1<-->call2\n\n");
  1948.   printf ("Linkinfo ist freie Software, unter den Bedingungen, die in\n");
  1949.   printf ("LICENCE beschrieben sind.\n");
  1950.   printf ("Die Autoren uebernehmen keine Garantie!\n\n");
  1951. }
  1952. int main(argc,argv)
  1953. int argc;
  1954. char **argv;
  1955. {
  1956.   char *rcs=ID;
  1957. #if OPTIONS && defined (UNIX)
  1958.   extern int optind;
  1959. #endif
  1960.   rcs [strlen(rcs)] = 1;
  1961.   rcs [strlen(rcs)] = 0;
  1962.   /* C-Optimizer ueberlisten, dass der Header im Executable drinsteht. */
  1963.  
  1964.   /* Consistency check */
  1965.   if( sizeof(short int) != 2 )internal(1,"sizeof(short int)!=2");
  1966.   if( sizeof(long int) != 4 )internal(2,"sizeof(long int)!=4");
  1967. #ifdef ATARI
  1968.   if (checksp (argc, argv)) {
  1969.     argc -= 3;
  1970.     /* SP/ATARI benoetigt es, dass LINKINFO seine Ausgabe umlenkt. */
  1971.     if (!freopen ("OUT.TXT", "w", stdout)) exit (1);
  1972.     memcpy (stderr, stdout, sizeof (FILE));
  1973.   }
  1974. #endif
  1975.   copyright();
  1976.   parse_options(argc,argv);
  1977. #if OPTIONS && defined (UNIX)
  1978.   if(optind==0)optind++;
  1979.   argc-=optind;argv+=optind; /* argc enthaelt die Zahl der eigentl.
  1980.                               * Argumente, argv zeigt auf die Liste
  1981.                               * der eigentlichen Argumente
  1982.                   */
  1983. #else
  1984.   argc--;argv++;
  1985. #endif
  1986. #ifndef ATARI
  1987.   if (checksp (argc, argv)) argc -= 3;
  1988. #endif
  1989.   switch(argc){
  1990.   case 0:
  1991.     if(asciinewer()){
  1992.       compile_data();
  1993.       data_info();
  1994.     } else {
  1995.       data_info();
  1996.     }
  1997.     usage();
  1998.     if (tmp_exists) unlink (tmpname);
  1999.     exit(0);
  2000.   case 1:
  2001.     /* Verschiedene Faelle: */
  2002.     {
  2003.       char *bp = argv[0];
  2004.       while (*bp && iswhitespace (*bp)) bp ++;
  2005.       if (! *bp) {
  2006.     load_data();
  2007.     info_prefix ("");
  2008.     free_data ();
  2009.     if (tmp_exists) unlink (tmpname);
  2010.     exit (0);
  2011.       }
  2012.     }
  2013.     if(qrgvalid(argv[0])){
  2014.       load_data();
  2015.       find_qrg(argv[0]);
  2016.       free_data();
  2017.       if (tmp_exists) unlink (tmpname);
  2018.       exit(0);
  2019.     }
  2020.     if(qthvalid(argv[0])){
  2021.       int laenge, breite;
  2022.       /* Einfache Aufgabe */
  2023.       strtoupper(argv[0]);
  2024.       while(iswhitespace(argv[0][0]))argv[0]++;
  2025.       laenge = (argv[0][0] - 'A') * 240 + (argv[0][2] - '0') * 24 +
  2026.     (argv[0][4] - 'A');
  2027.       breite = (argv[0][1] - 'A') * 240 + (argv[0][3] - '0') * 24 +
  2028.     (argv[0][5] - 'A');
  2029.       printf ("%.6s ist ", argv[0]);
  2030.       printcoord (laenge, breite);
  2031.       printf("\n\n");
  2032.       if (tmp_exists) unlink (tmpname);
  2033.       exit(0);
  2034.     }
  2035.     load_data();
  2036.     if(!info_call(argv[0])){
  2037.       free_data();
  2038.       if (tmp_exists) unlink (tmpname);
  2039.       exit(0);
  2040.       /* Kein Fehler -> Call gefunden */
  2041.     }
  2042.     info_prefix(argv[0]);
  2043.     free_data();
  2044.     if (tmp_exists) unlink (tmpname);
  2045.     exit(0);
  2046.   default:
  2047.     load_data();
  2048.     do_exclusions(argc-2,argv+2, argv [0], argv [1]);
  2049.     find_route (argv [0], argv [1]);
  2050.     free_data();
  2051.     if (tmp_exists) unlink (tmpname);
  2052.     exit(0);
  2053.   }
  2054.   return 0;
  2055. }
  2056. int checksp (argc, argv)
  2057. int argc;
  2058. char **argv;
  2059. {
  2060.   char *bp, call [7];
  2061.   if (argc < 3) return 0;
  2062.   bp = argv [argc - 3];
  2063.   while (*bp && iswhitespace (*bp)) bp ++;
  2064.   if (*bp < '0' || *bp > '9') return 0;
  2065.   bp ++;
  2066.   while (*bp && iswhitespace (*bp)) bp ++;
  2067.   if (*bp) return 0;
  2068.   bp = argv [argc - 2];
  2069.   while (*bp && iswhitespace (*bp)) bp ++;
  2070.   if (*bp < '0' || *bp > '9') return 0;
  2071.   bp ++;
  2072.   while (*bp && iswhitespace (*bp)) bp ++;
  2073.   if (*bp) return 0;
  2074.   bp = parse_call (argv [argc - 1], call);
  2075.   if (bp == argv [argc - 1]) return 0;
  2076.   while (*bp && iswhitespace (*bp)) bp ++;
  2077.   if (*bp) return 0;
  2078.   return 1;
  2079. }
  2080.